module qtrt
import ffi

type T_ZNK7QObject10metaObjectEv = fn(cthis voidptr) voidptr/*666*/
type T_ZNK11QMetaObject13indexOfSignalEPKc = fn(cthis voidptr, signal voidptr) int
type T_ZNK11QMetaObject6methodEi = fn(cthis voidptr, index int) voidptr
type T_ZNK11QMetaMethod14parameterCountEv = fn(cthis voidptr) int
type T_ZNK11QMetaMethod13parameterTypeEi = fn(cthis voidptr, index int) int

// maybe use a simple signature parser
// return type is ffitype
fn get_signal_argtys(obj voidptr, signal string) []int {
    // TODO metaobject , metamethod,
    mut res := []int{}
    signame := signal.all_before("(")

    mut mto := vnil
    if true {
        mut fnobj := T_ZNK7QObject10metaObjectEv(0)
        fnobj = sym_qtfunc6(0, "_ZNK7QObject10metaObjectEv")
        rv := fnobj(obj)
        mto = rv
    }
    assert mto != vnil

    mut sigidx := 0
    if true {
        conv_arg0 := signal.str
        mut fnobj := T_ZNK11QMetaObject13indexOfSignalEPKc(0)
        fnobj = sym_qtfunc6(0, "_ZNK11QMetaObject13indexOfSignalEPKc")
        rv := fnobj(mto, conv_arg0)
        sigidx = rv
    }
    if sigidx == -1 {
        println("sigidx -1 for ${signal} ${mto}")
    }
    assert sigidx != -1

    mut mth := vnil
    if true {
        index := sigidx
        mut fnobj := T_ZNK11QMetaObject6methodEi(0)
        fnobj = qtrt.sym_qtfunc6(0,"_ZNK11QMetaObject6methodEi")
        rv := fnobj(mto, index)
        mth = rv
    }
    assert mth != vnil

    mut prmcnt := 0
    if true {
        mut fnobj := T_ZNK11QMetaMethod14parameterCountEv(0)
        fnobj = qtrt.sym_qtfunc6(0,"_ZNK11QMetaMethod14parameterCountEv")
        rv := fnobj(mth)
        prmcnt = rv
    }

    if true {
        mut fnobj := T_ZNK11QMetaMethod13parameterTypeEi(0)
        fnobj = qtrt.sym_qtfunc6(0,"_ZNK11QMetaMethod13parameterTypeEi")
        for index in 0..prmcnt {
            rv := fnobj(mth, index)
            ffity := qmetatype2ffi(rv)
            println("typemap ${rv}=>${ffity} of ${signal}[${index}]")
            res << ffity
        }
    }

    return res
}

enum QMetaType {
    mtbool = 1
    mtint = 2
    mtuint = 3
    mtdouble = 6
    mtlong = 32
    mtlonglong = 4
    mtulong = 35
    mtulonglong = 5
    mtshort = 34
    mtushort = 36
    mtschar = 40
    mtuchar = 37
    mtfloat = 38
}
fn qmetatype2ffi(typ int) int {
    match QMetaType(typ) {
            .mtbool { return ffi.TYPE_INT }
            .mtint      { return ffi.TYPE_INT }
            .mtuint     { return ffi.TYPE_INT }
            .mtdouble   { return ffi.TYPE_DOUBLE }
            .mtlong     { return ffi.TYPE_INT }
            .mtlonglong { return ffi.TYPE_SINT64 }
            .mtulong    { return ffi.TYPE_INT }
            .mtulonglong{ return ffi.TYPE_UINT64 }
            .mtshort    { return ffi.TYPE_SINT16 }
            .mtushort   { return ffi.TYPE_UINT16 }
            .mtschar    { return ffi.TYPE_SINT8 }
            .mtuchar    { return ffi.TYPE_UINT8 }
            .mtfloat    { return ffi.TYPE_FLOAT }
        //else { return ffi.TYPE_POINTER }
    }
    return ffi.TYPE_POINTER
}
